#pragma once

#include <map>
#include <memory>
#include <cassert>
#include "DRStruct.hpp"

namespace Alice
{

/*
    反射管理器
    注册和管理支持反射的组件（结构体）
*/
class ReflMngr
{
public:
    /*
        注册一个结构体
        需使用到一个已经绑定好类型信息的 DRStruct
    */
    template<class StructType>
    void Register(DRStruct<StructType>& DR_struct)
    {
        const char* type_name = typeid(StructType).name();

        if (m_structs.find(type_name) == m_structs.end())
        {
            m_structs.insert({
                type_name, 
                std::make_shared<DRStruct<StructType> >(DR_struct)
            });
        }
    }

    /*
        查看一个结构体对象的类型信息
    */
    template<class StructType>
    void Info(StructType& obj)
    {
        const char* type_name = typeid(StructType).name();

        assert(
            m_structs.find(type_name) != m_structs.end() &&
            "The structure is not registered"
        );

        std::shared_ptr<DRStruct<StructType> > struct_ptr
            = std::static_pointer_cast<DRStruct<StructType> >
        (
            m_structs[ type_name ]
        );

        std::cout << type_name << "\n{" << std::endl;
        struct_ptr->Info(obj);
        std::cout << "}" << std::endl;
    }

private:
    // 已被注册过得结构体
    std::map<const char*, std::shared_ptr<DRStructBase> > m_structs;
};

} // namespace Alice
